home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2003 November A / PCWK1103A.iso / ABBYY FineReader 7.0 PRO / data1.cab / gs_cff.ps < prev    next >
Text File  |  2002-02-23  |  22KB  |  758 lines

  1. %    Copyright (C) 1997, 1998, 1999, 2000 Aladdin Enterprises.  All rights reserved.
  2. % This software is provided AS-IS with no warranty, either express or
  3. % implied.
  4. % This software is distributed under license and may not be copied,
  5. % modified or distributed except as expressly authorized under the terms
  6. % of the license contained in the file LICENSE in this distribution.
  7. % For more information about licensing, please refer to
  8. % http://www.ghostscript.com/licensing/. For information on
  9. % commercial licensing, go to http://www.artifex.com/licensing/ or
  10. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. % San Rafael, CA  94903, U.S.A., +1(415)492-9861.
  12.  
  13. % $Id: gs_cff.ps,v 1.10.2.1 2002/02/22 19:45:55 ray Exp $
  14. % Loader for CFF (compressed) fonts, including OpenType CFFs.
  15. % The following are not implemented yet:
  16. %    Deleted entries in the Name Index
  17. %    Embedded PostScript
  18. %    Multiple Master fonts
  19. %    Chameleon fonts
  20. %    Synthetic fonts
  21.  
  22. % ---------------- Font loading machinery ---------------- %
  23.  
  24. % Augment the FONTPATH machinery so it recognizes OpenType CFF font sets.
  25.  
  26. /.scanfontheaders where {
  27.   pop /.scanfontheaders [
  28.    .scanfontheaders aload pop (OTTO*)
  29.   ] def
  30. } if
  31.  
  32. % Load a font file that might be an OpenType CFF font set.
  33.  
  34. % <file> .loadfontfile -
  35. /.loadnonottofontfile /.loadfontfile load def
  36. /.loadfontfile {
  37.   dup 4 string .peekstring pop (OTTO) eq {
  38.         % If this is a font at all, it's an OpenType CFF font set.
  39.     .loadottofontfile
  40.   } {
  41.         % Not a TrueType font.
  42.     .loadnonottofontfile
  43.   } ifelse
  44. } bind def
  45.  
  46. % <file> .loadottofontfile -
  47. /.loadottofontfile {
  48.   /FontSetInit /ProcSet findresource begin
  49.   2 dict begin
  50.   /f exch def /cff null def
  51.   card32 pop card16 6 { next pop } repeat dup {
  52.         % Stack: numtables tablesleft
  53.     dup 0 eq {
  54.       pop pop /.loadottofontfile cvx /invalidfont signalerror
  55.     } if
  56.     f 4 string readstring pop (CFF ) eq { sub exit } if
  57.     1 sub
  58.   } loop
  59.         % Stack: tablesread
  60.   card32 pop card32 card32
  61.         % Stack: tablesread start length
  62.   exch 3 -1 roll 1 add 16 mul 12 add sub
  63.   f exch subfilefilter flushfile    % skip to start
  64.   f exch subfilefilter end
  65.     % Use a random FontSet resource name.  ****** WRONG ******
  66.   realtime rand xor =string cvs exch false
  67.   ReadData
  68. } bind def
  69.  
  70. 30 dict begin
  71.  
  72. % ---------------- Standard strings (actually names) ---------------- %
  73.  
  74. /StandardStrings mark
  75.     % The initial StandardStrings that that denote characters are
  76.     % defined as a pseudo-Encoding.
  77. % 0
  78.   /CFFStandardStrings .findencoding aload pop
  79. % 379
  80.   (001.000)
  81. % 380
  82.   (001.001) (001.002) (001.003) /Black /Bold
  83.   /Book /Light /Medium /Regular /Roman
  84.   /Semibold
  85. .packtomark def
  86.  
  87. % ---------------- Standard encodings ---------------- %
  88.  
  89. /StandardEncodings [
  90.  
  91. % StandardEncoding
  92. mark
  93.   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  94.   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  95.   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  96.   17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
  97.   33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
  98.   49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
  99.   65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
  100.   81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 0
  101.   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  102.   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  103.   0 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
  104.   0 111 112 113 114 0 115 116 117 118 119 120 121 122 0 123
  105.   0 124 125 126 127 128 129 130 131 0 132 133 0 134 135 136
  106.   137 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  107.   0 138 0 139 0 0 0 0 140 141 142 143 0 0 0 0
  108.   0 144 0 0 0 145 0 0 146 147 148 149 0 0 0 0
  109. .packtomark
  110.  
  111. % ExpertEncoding
  112. mark
  113.   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  114.   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  115.   1 229 230 0 231 232 233 234 235 236 237 238 13 14 15 99
  116.   239 240 241 242 243 244 245 246 247 248 27 28 249 250 251 252
  117.   0 253 254 255 256 257 0 0 0 258 0 0 259 260 261 262
  118.   0 0 263 264 265 0 266 109 110 267 268 269 0 270 271 272
  119.   273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
  120.   289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 0
  121.   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  122.   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  123.   0 304 305 306 0 0 307 308 309 310 311 0 312 0 0 313
  124.   0 0 314 315 0 0 316 317 318 0 0 0 158 155 163 319
  125.   320 321 322 323 324 325 0 0 326 150 164 169 327 328 329 330
  126.   331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
  127.   347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
  128.   363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
  129. .packtomark
  130.  
  131. ] readonly def
  132.  
  133. % ---------------- Standard Charsets ---------------- %
  134.  
  135. % We include an explicit 0 at the beginning of each charset.
  136.  
  137. /StandardCharsets [
  138.  
  139. % ISOAdobe
  140. mark
  141.   0
  142.   1 1 228 { } for
  143. .packtomark
  144.  
  145. % Expert
  146. mark
  147.   0
  148.   1 229 230 231 232 233 234 235 236 237 238 13 14 15 99 239
  149.   240 241 242 243 244 245 246 247 248 27 28 249 250 251 252 253
  150.   254 255 256 257 258 259 260 261 262 263 264 265 266 109 110 267
  151.   268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
  152.   284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
  153.   300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
  154.   316 317 318 158 155 163 319 320 321 322 323 324 325 326 150 164
  155.   169 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
  156.   342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
  157.   358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
  158.   374 375 376 377 378
  159. .packtomark
  160.  
  161. % ExpertSubset
  162. mark
  163.   0
  164.   1 231 232 235 236 237 238 13 14 15 99 239 240 241 242 243
  165.   244 245 246 247 248 27 28 249 250 251 253 254 255 256 257 258
  166.   259 260 261 262 263 264 265 266 109 110 267 268 269 270 272 300
  167.   301 302 305 314 315 158 155 163 320 321 322 323 324 325 326 150
  168.   164 169 327 328 329 330 331 332 333 334 335 336 337 338 339 340
  169.   341 342 343 344 345 346
  170. .packtomark
  171.  
  172. ] readonly def
  173.  
  174. % ---------------- Font loading ---------------- %
  175.  
  176. % ------ Utilities ------ %
  177.  
  178. /advance {    % <n> advance -
  179.   f cff eq { pos add /pos exch store } { pop } ifelse
  180. } bind def
  181. /next {        % - next <byte>
  182.   f read {
  183.     1 advance
  184.     DEBUG { (  ) print dup = } if
  185.   } if
  186. } bind def
  187. /next2 {    % - next2 <byte1> <byte2>
  188.   f read {
  189.     f read {
  190.       2 advance
  191.       DEBUG { (  ) print 1 index =only (,) print dup = } if
  192.     } {
  193.       1 advance
  194.       DEBUG { (  ) print dup = } if
  195.     } ifelse
  196.   } if
  197. } bind def
  198. /nextstring {    % <length> nextstring <string>
  199.   dup 0 eq {
  200.     pop ()
  201.   } {
  202.     string f exch readstring pop dup length advance
  203.     DEBUG { (  ) print dup == } if
  204.   } ifelse
  205. } bind def
  206. /card8        % - card8 <card8>
  207.  /next load
  208. def
  209. /card16 {    % - card16 <card16>
  210.   next2 exch 8 bitshift add
  211. } bind def
  212. /card32 {    % - card32 <card32>
  213.   card16 16 bitshift card16 add
  214. } bind def
  215. /offsetprocs [
  216.   /card8 load
  217.   /card16 load
  218.   { card8 16 bitshift card16 add } bind
  219.   /card32 load
  220. ] readonly def
  221. /offsetproc {    % <offsize> offsetproc <proc>
  222.   1 sub //offsetprocs exch get
  223. } bind def
  224. /offset {    % <offsize> offset <offset>
  225.   offsetproc exec
  226. } bind def
  227. /sid        % - <sid> sid
  228.   /card16 load
  229. def
  230. /Index {    % - Index <array>
  231.   mark card16 dup 0 ne {
  232.     1 exch next offsetproc dup exec pop exch {
  233.       dup exec dup 4 -1 roll sub 3 1 roll exch
  234.     } repeat pop
  235.   } if pop .packtomark
  236.   [ exch { nextstring } forall ] readonly
  237. } bind def
  238. /tokens {    % - tokens <num1> ... <op#> (op# = 12 means EOF)
  239.   {
  240.     f read not { 12 exit } if
  241.     DEBUG { (..) print dup = } if
  242.     1 advance
  243.     dup 12 eq { pop next 32 add exit } if
  244.     dup 28 lt { exit } if
  245.     dup 32 lt {
  246.       28 sub {
  247.     { card16 32768 xor 32768 sub }
  248.     { 4 offset dup 16#7fffffff gt { -1 32 bitshift add } if }
  249.     { tokenreal }
  250.     { 31 exit }
  251.       } exch get exec
  252.     } {
  253.       dup 247 lt {
  254.     139 sub
  255.       } {
  256.     247 sub {
  257.       { next 108 add }
  258.       { next 364 add }
  259.       { next 620 add }
  260.       { next 876 add }
  261.       { next 108 add neg }
  262.       { next 364 add neg }
  263.       { next 620 add neg }
  264.       { next 876 add neg }
  265.       % 255 is deliberately omitted and will cause a rangecheck
  266.     } exch get exec
  267.       } ifelse
  268.     } ifelse
  269.   } loop
  270. } bind def
  271. /tokenbuf 100 string def
  272. /tokenput {    % <index> <char> tokenput <index+1>
  273.   tokenbuf 2 index 3 -1 roll put 1 add
  274. } bind def
  275. /tokenrealarray [
  276.  (0123456789.E) { } forall
  277.  [(E) 0 get /tokenput cvx (-) 0 get] cvx
  278.  null        % will give an error
  279.  (-) 0 get
  280.  { exit }
  281. ] readonly def
  282. /tokenreal {    % - tokenreal <float>
  283.   0 {
  284.     next exch 1 index -4 bitshift tokenrealarray exch get exec tokenput
  285.         % We must leave the byte on the stack temporarily so that
  286.         % the exit will see a consistent stack state.
  287.     1 index 15 and tokenrealarray exch get exec tokenput exch pop
  288.   } loop
  289.   tokenbuf 0 3 -1 roll getinterval cvr exch pop
  290. } bind def
  291. /Dict {        % <opsdict> Dict -
  292.   /opdict exch store {
  293.     mark tokens
  294.     DEBUG { (tokens: ) print ] dup === mark exch aload pop } if
  295.     opdict exch .knownget { exec } if cleartomark
  296.   } loop cleartomark
  297. } bind def
  298. /idstring {    % <sid> idstring <string|name>
  299.   dup 391 lt { //StandardStrings } { 391 sub strings } ifelse exch get
  300. } bind def
  301. /idname {    % <sid> idname <name>
  302.   idstring dup type /nametype ne { cvn } if
  303. } bind def
  304. /subfilefilter {    % <file> <length> subfilefilter <filter>
  305.     % SubFileDecode interprets a length of 0 as infinite.
  306.   dup 0 le { pop pop () 0 } if () /SubFileDecode filter
  307. } bind def
  308.  
  309. % ------ Top dictionary ------ %
  310.  
  311. /offput {    % <offset> <proc> offput -
  312.   DEBUG { (queued: ) print 1 index =only ( ) print dup === } if
  313.   currentdict exch aload length 1 add packedarray cvx
  314.   offsets 3 1 roll put
  315. } bind def
  316. /queueput {    % <font> <proc> queueput -
  317.   16#7fffffff offsets { pop .min } forall
  318.   pos sub nextstring
  319.   3 1 roll aload length 2 add packedarray cvx
  320.   [ queued aload pop counttomark 2 add -1 roll ]
  321.   /queued exch store
  322. } bind def
  323. /xxput {    % <value> <key> <dict> xxput -
  324.   3 1 roll exch put
  325. } bind def
  326. /putfi {    % <value> <key> putfi -
  327.   FontInfo xxput
  328. } bind def
  329. /xdef {        % <value> <key> xdef -
  330.   exch def
  331. } bind def
  332. /topdictops mark
  333.   12 { exit }
  334.   0 { idstring /version putfi }
  335.   1 { idstring /Notice putfi }
  336.   32 { idstring /Copyright putfi }
  337.   2 { idstring /FullName putfi }
  338.   3 { idstring /FamilyName putfi }
  339.   4 { idstring /Weight putfi }
  340.   33 { 0 ne /isFixedPitch putfi }
  341.   34 { /ItalicAngle putfi }
  342.   35 { /UnderlinePosition putfi }
  343.   36 { /UnderlineThickness putfi }
  344.   37 { /PaintType xdef }
  345.   38 { /FontType xdef }        % actually CharstringType
  346.   39 { counttomark array astore /FontMatrix xdef }
  347.   13 { /UniqueID xdef }
  348.   5 { counttomark array astore /FontBBox xdef }
  349.   40 { /StrokeWidth xdef }
  350.   14 { counttomark array astore /XUID xdef }
  351.   15 {
  352.     dup StandardCharsets length lt {
  353.       StandardCharsets exch get /charset xdef
  354.     } {
  355.       { queuecharset } offput
  356.     } ifelse
  357.   }
  358.   16 {
  359.     dup StandardEncodings length lt {
  360.       /Encoding xdef
  361.     } {
  362.       { queueEncoding } offput
  363.     } ifelse
  364.   }
  365.   17 { { readCharStrings } offput }
  366.   18 { exch /readPrivate cvx 2 packedarray offput }
  367.     % CIDFont operators
  368.   62 {        % ROS, must be first in a CIDFont
  369.     currentdict /FontType undef
  370.     currentdict /Encoding undef
  371.     currentdict /FontMatrix undef
  372.     /CIDFontVersion 0 def
  373.     /CIDFontRevision 0 def
  374.     /CIDFontType 0 def
  375.     /CIDCount 8720 def % Default value defined in CFF spec.
  376.     3 dict begin
  377.     /Supplement xdef
  378.     idstring /Ordering xdef
  379.     idstring /Registry xdef
  380.     /CIDSystemInfo currentdict end def
  381.   }
  382.   63 { /CIDFontVersion xdef }
  383.   64 { /CIDFontRevision xdef }
  384.   65 { /CIDFontType xdef }
  385.   66 { /CIDCount xdef }
  386.   67 { /UIDBase xdef }
  387.   68 { { readFDArray } offput }
  388.   69 { { readFDSelect } offput }
  389.     % This operator only appears in a FDArray element.
  390.   70 { idstring /FontName exch def }
  391. .dicttomark readonly def
  392.  
  393. % readcharset and readFDSelect may require the length of CharStringArray,
  394. % but these structures may occur in the file before the CharStrings.
  395. % If that happens, use a hack: assume that all the data up to the next
  396. % queued read should be read.
  397.  
  398. /charstringcount {    % <font> charstringcount <count> true
  399.             % <font> charstringcount <length> false
  400.   /CharStringArray .knownget {
  401.     length true
  402.   } {
  403.     % Hack: look for the next queued read.
  404.     16#7fffffff offsets { pop .min } forall
  405.     pos sub false
  406.   } ifelse
  407. } bind def
  408.  
  409. /readCharStrings {    % <font> readCharStrings -
  410.   /CharStringArray Index put
  411. } bind def
  412.  
  413. % ------ Charsets and encodings ------ %
  414.  
  415. % Note: formats 1 and 2 can overflow the operand stack.
  416. % We'll fix this if it ever becomes necessary.
  417. /charsetcount {
  418.   charstringcount { 1 sub } { 2 idiv } ifelse
  419. } bind def
  420. /charsetformats [
  421. { [ 0 3 -1 roll charsetcount { sid } repeat ]
  422. } bind
  423. { [ 0 3 -1 roll charsetcount {
  424.     dup 0 eq { pop exit } if
  425.     sid card8 1 add 2 index .min { exch 1 sub 1 index 1 add } repeat pop
  426.   } loop ]
  427. } bind
  428. { [ 0 3 -1 roll charsetcount {
  429.     dup 0 eq { pop exit } if
  430.     sid card16 1 add 2 index .min { exch 1 sub 1 index 1 add } repeat pop
  431.   } loop ]
  432. } bind
  433. ] readonly def
  434. /queuecharset {        % <font> queuecharset -
  435.   { readcharset } queueput
  436. } bind def
  437. /readcharset {        % <data> <font> readcharset -
  438.   begin 0 () /SubFileDecode filter /f exch store
  439.   charsetformats next get currentdict exch exec /charset exch def end
  440. } bind def
  441.  
  442. /encodingformats [
  443. { 1 1 next { next exch Encoding 3 1 roll put } for
  444. } bind
  445. { 1 next {
  446.     next next 1 add {
  447.             % Stack: gid code
  448.       Encoding 1 index 3 index put
  449.       exch 1 add exch 1 add
  450.     } repeat pop
  451.   } repeat pop
  452. } bind
  453. ] readonly def
  454. /queueEncoding {    % <font> queueEncoding -
  455.   { readEncoding } queueput
  456. } bind def
  457. /readEncoding {        % <data> <font> readEncoding -
  458.   begin 0 () /SubFileDecode filter /f exch store
  459.   /Encoding [ 256 { /.notdef } repeat ] def
  460.   next encodingformats 1 index 127 and get exec
  461.   128 ge {
  462.             % Read supplementary encodings.
  463.     next {
  464.       Encoding next sid idname put
  465.     } repeat
  466.   } if end
  467. } bind def
  468.  
  469. % ------ FDArray and FDSelect ------ %
  470.  
  471. /readFDArray {        % <font> readFDArray -
  472.   Index exch
  473.   2 dict begin /f null def begin
  474.   [ exch {
  475.     dup length subfilefilter /f exch store
  476.     10 dict begin
  477.     /FontType 2 def
  478.     /PaintType 0 def
  479.     /FontMatrix [0.001 0 0 0.001 0 0] def
  480.     /Private 20 dict def
  481.     //topdictops Dict currentdict end
  482.   } forall ] /FDArray xdef end end
  483. } bind def
  484.  
  485. % Note: this implementation can overflow the operand stack.
  486. % We'll fix this if it ever becomes necessary.
  487. /fdselectformats [
  488. { [ exch charstringcount pop { card8 } repeat ] } bind
  489. { /FDSelect cvx /invalidfont signalerror } bind
  490. dup
  491. { pop [ card16 card16 exch {
  492.         % Stack: previndex
  493.     card8 card16 dup 4 1 roll 3 -1 roll sub 1 sub {
  494.       exch 1 index
  495.     } repeat exch
  496.   } repeat pop ]
  497. } bind
  498. ] readonly def
  499.  
  500. /readFDSelect {        % <font> readFDSelect -
  501.   begin fdselectformats next get currentdict exch exec /FDSelect exch def end
  502. } bind def
  503.  
  504.  
  505. % ------ Private dictionary ------ %
  506.  
  507. /deltarray {        % -mark- <num1> ... deltarray <num1'> ...
  508.   0 counttomark 1 sub { counttomark -1 roll add dup } repeat pop
  509.   counttomark array astore
  510. } bind def
  511.  
  512. /privatedictops mark
  513.   12 { exit }
  514.   6 { deltarray /BlueValues xdef }
  515.   7 { deltarray /OtherBlues xdef }
  516.   8 { deltarray /FamilyBlues xdef }
  517.   9 { deltarray /FamilyOtherBlues xdef }
  518.   41 { /BlueScale xdef }
  519.   42 { /BlueShift xdef }
  520.   43 { /BlueFuzz xdef }
  521.   10 { 1 array astore /StdHW xdef }
  522.   11 { 1 array astore /StdVW xdef }
  523.   44 { deltarray /StemSnapH xdef }
  524.   45 { deltarray /StemSnapV xdef }
  525.   46 { 0 ne /ForceBold xdef }
  526.   47 { /ForceBoldThreshold xdef }
  527.   48 { /lenIV xdef }
  528.   49 { /LanguageGroup xdef }
  529.   50 { /ExpansionFactor xdef }
  530.   51 { /initialRandomSeed xdef }
  531.   19 { PrivateStart add { readSubrs } offput }
  532.   20 { /defaultWidthX xdef }
  533.   21 { /nominalWidthX xdef }
  534.     % Multiple Master fonts only
  535.   59 { /NDV xdef }
  536.   60 { /CDV xdef }
  537.   61 { /lenBuildCharArray xdef }
  538. .dicttomark readonly def
  539.  
  540. /readPrivate {        % <font> <size> readPrivate -
  541.   2 dict begin
  542.   /PrivateStart pos def
  543.   f 3 1 roll exch 1 index f exch subfilefilter /f exch store
  544.   dup /FontType get exch
  545.   /Private get begin
  546.         % Default lenIV to -1 even for Type 1 CharStrings.
  547.   2 ne { /lenIV -1 def } if
  548.   //privatedictops Dict end
  549.   exch /f exch store advance
  550.   end
  551. } bind def
  552.  
  553. /readSubrs {        % <font> readSubrs -
  554.   /Subrs Index put
  555. } bind def
  556.  
  557. % ------ Main program ------ %
  558.  
  559. % Clean up after finishing a font.
  560. /cleanupFont {        % (currentdict) cleanupFont -
  561.         % Remove unwanted entries.
  562.   currentdict /charset undef
  563.   currentdict /CharStringArray undef
  564. } bind def
  565.  
  566. % Update the Encoding and CharStrings for a real font.
  567. /finishFont {        % (currentdict) finishFont -
  568.         % Construct the real Encoding.
  569.         % The value of Encoding is either a number, for predefined
  570.         % encodings, or an array of mixed GIDs and names.
  571.   /Encoding mark Encoding
  572.   DEBUG { (Encoding: ) print dup === flush } if
  573.   dup type /integertype eq {
  574.     StandardEncodings exch get { idname } forall
  575.   } {
  576.     {
  577.       dup type /integertype eq { charset exch get idname } if
  578.     } forall
  579.   } ifelse .packtomark def
  580.         % Construct the CharStrings.
  581.         % Note that they may only correspond to an initial
  582.         % subset of the charset.
  583.   /CharStrings charset length CharStringArray length .min dict def
  584.   DEBUG {
  585.     charset length =only ( charset ) print
  586.     CharStringArray length =only ( CharStringArray) =
  587.     charset == flush
  588.   } if
  589.   0 1 CharStrings maxlength 1 sub {
  590.     dup CharStringArray exch get
  591.     exch charset exch get idstring CharStrings xxput
  592.   } for
  593.   cleanupFont
  594. } bind def
  595.  
  596. % Replace CharStrings with GlyphDirectory for a CIDFont;
  597. % Move GlobalSubrs to descendent fonts.
  598. /finishCIDFont {    % (currentdict) finishCIDFont -
  599.         % Construct the GlyphDirectory, similar to CharStrings.
  600.   /FDBytes FDArray length 1 gt { 1 } { 0 } ifelse def
  601.   /GlyphDirectory charset length CharStringArray length .min dict def
  602.   DEBUG {
  603.     charset length =only ( charset ) print
  604.     CharStringArray length =only ( CharStringArray) =
  605.     charset == flush
  606.   } if
  607.   0 1 GlyphDirectory maxlength 1 sub {
  608.     dup CharStringArray exch get
  609.         % If there is more than one FDArray entry, add the font
  610.         % index to the beginning of each charstring.
  611.     FDBytes 1 eq {
  612.       FDSelect 2 index get
  613.       1 string dup 0 4 -1 roll put exch concatstrings
  614.     } if
  615.     exch charset exch get GlyphDirectory xxput
  616.   } for
  617.  
  618.   Private /GlobalSubrs .knownget {
  619.     FDArray {
  620.     /Private get /GlobalSubrs 2 index put
  621.     } forall
  622.     pop
  623.     Private /GlobalSubrs undef
  624.   } if
  625.  
  626.         % Clean up.
  627.   currentdict /FDSelect undef
  628.   cleanupFont
  629. } bind def
  630. % We need to pass the file as a parameter for the sake of the PDF
  631. % interpreter. Also for the sake of PDF, a flag forces the font
  632. % to be defined as <resname> instead of the name embedded in the data.
  633. % This is needed for subsetted fonts; it is valid if the CFF
  634. % contains only a single font.
  635. /StartData {          % <resname> <nbytes> StartData -
  636.   currentfile exch subfilefilter false ReadData
  637. } bind def
  638. /ReadData {           % <resname> <file> <forceresname> ReadData -
  639.  
  640.     % Initialize.
  641.  
  642.   30 dict begin
  643.   /forceresname exch def
  644.   /cff exch def
  645.   /pos 0 def
  646.   /resname exch cvlit def
  647.   /DEBUG DEBUG def    % bring the binding closer
  648.  
  649.     % Read the header.
  650.  
  651.   /f cff def
  652.   /vmajor next def
  653.   /vminor next def
  654.   /hdrsize next def
  655.   /aoffsize next def
  656.  
  657.     % Read the Indexes.
  658.  
  659.   /names Index def
  660.   /topdicts Index def
  661.   /strings Index def
  662.   /gsubrs Index def
  663.  
  664.     % Read the top Dicts.
  665.  
  666.   /offsets 50 dict def
  667.   /queued [] def
  668.   /opdict null def        % reserve a slot
  669.   /fonts [ topdicts {
  670.     0 () /SubFileDecode filter /f exch def
  671.     40 dict begin
  672.         % Preload defaults that differ from PostScript defaults,
  673.         % or that are required.
  674.       /FontType 2 def
  675.       /PaintType 0 def
  676.       /FontMatrix [0.001 0 0 0.001 0 0] def
  677.       /charset StandardCharsets 0 get def
  678.       /Encoding 0 def
  679.       /FontInfo 10 dict
  680.     dup /UnderlinePosition -100 put
  681.     dup /UnderlineThickness 50 put
  682.       def
  683.       /Private 20 dict
  684.     gsubrs length 0 ne { dup /GlobalSubrs gsubrs put } if
  685.       def
  686.       //topdictops Dict
  687.     currentdict end
  688.   } forall ] def
  689.  
  690.     % Read other tables with queued offsets.
  691.  
  692.   DEBUG { (offsets: ) print [ offsets { pop } forall ] == } if
  693.   { /f cff def
  694.     DEBUG { (pos=) print pos = } if
  695.     offsets pos 2 copy .knownget not { pop pop exit } if
  696.     3 1 roll undef
  697.     DEBUG { (exec queued: ) print dup == } if
  698.     exec
  699.   } loop
  700.   offsets length 0 ne {
  701.     (Error: missing tables at ) print [ offsets { pop } forall ] ==
  702.     (Current position is ) print pos ==
  703.     flush stop
  704.   } if
  705.  
  706.     % Process out-of-order tables.
  707.  
  708.   DEBUG { queued length =only ( queued) = flush } if
  709.   queued { exec } forall
  710.  
  711.     % Update Encoding and CharStrings.
  712.  
  713.   fonts {
  714.     begin
  715.     currentdict /CIDFontType known { finishCIDFont } { finishFont } ifelse
  716.     end
  717.   } forall
  718.  
  719.     % Wrap up.
  720.  
  721.   resname mark 0 1 fonts length 1 sub {
  722.     DEBUG { dup =only ( ) print flush } if
  723.     dup names exch get
  724.     forceresname { pop resname } if
  725.     DEBUG { dup == flush } if
  726.     exch fonts exch get
  727.     dup /CIDFontType known {
  728.         % This is a CIDFont.
  729.       dup /CIDFontName 3 index put
  730.       1 index exch /CIDFont defineresource
  731.     } {
  732.         % This is a font.
  733.       dup /FontName 3 index put
  734.       1 index exch definefont
  735.     } ifelse
  736.   } for .dicttomark
  737.   end        % temporary dict
  738.   end        % FontSetInit ProcSet
  739.   /FontSet defineresource pop
  740.  
  741. } bind def
  742.  
  743. % ---------------- Resource category definition ---------------- %
  744.  
  745. currentdict end readonly
  746.  
  747. languagelevel exch 2 .setlanguagelevel
  748.  
  749. /FontSet /Generic /Category findresource dup length dict .copydict
  750. /Category defineresource pop
  751.  
  752. /FontSetInit exch /ProcSet defineresource pop
  753.  
  754. .setlanguagelevel
  755.